package com.tlvip.design.singleton.inner;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * <p>description：</p>
 * <p>copyright： copyright(C)2016-2099</p>
 * <p>Life is short,we need passion</p>
 * <p>Summary： </p>
 * <p>instructions： </p>
 * Date 2021/8/15</p>
 * Author mac
 *
 * @version 1.0
 */
public class InnerClassSingleton {
    public static void main(String[] args) {
//        new Thread(() -> {
//            System.out.println(InnerSingleton.getInstance());
//        }).start();
//        new Thread(() -> {
//            System.out.println(InnerSingleton.getInstance());
//        }).start();

        try {
            Constructor<InnerSingleton> declaredConstructor = InnerSingleton.class.getDeclaredConstructor();
            declaredConstructor.setAccessible(true);
            InnerSingleton innerSingleton = declaredConstructor.newInstance();

            InnerSingleton instance = InnerSingleton.getInstance();
            // false 通过反射方式攻击，会有问题
            System.out.println(innerSingleton == instance);

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}

// 静态内部类懒加载实现
class InnerSingleton {
    private static class InnerClassHolder {
        private static InnerSingleton innerSingleton = new InnerSingleton();
    }

    private InnerSingleton() {
        // 防止反射方式攻击，单例模式不允许多个实例
        if (InnerClassHolder.innerSingleton != null) {
            throw new RuntimeException("单例模式不允许多个实例存在");
        }
    }

    // 本质 懒加载 ，使用类加载机制保证线程安全性
    public static InnerSingleton getInstance() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 当调用内部类静态属性时，触发内部类InnerClassHolder初始化，从而触发对象实例化
        return InnerClassHolder.innerSingleton;
    }
}